const jwt = require('jsonwebtoken')

const userService = require('../service/user.service')
const authService = require('../service/Auth.service')
const errorTypes = require('../constants/error-types')
const md5Password = require('../utils/password-handle')

const { PUBLIC_KEY } = require('../app/config')

const verifyLogin = async (ctx, next) => {
  const { name, password } = ctx.request.body

  if (!name || !password) {
    const error = new Error(errorTypes.NAME_OR_PASSWORD_IS_REQUIRED)
    return ctx.app.emit('error', error, ctx)
  }

  // 判断用户名是否存在
  const result = await userService.getUserByName(name)
  const user = result[0]
  if (!user) {
    const error = new Error(errorTypes.USER_DOES_NOT_EXISTS)
    return ctx.app.emit('error', error, ctx)
  }

  // 判断密码是否正确
  if (md5Password(password) !== user.password) {
    const error = new Error(errorTypes.PASSWORD_IS_INCORRENT)
    return ctx.app.emit('error', error, ctx)
  }
  ctx.user = user
  await next()
}

const verifyAuth = async (ctx, next) => {
  const authorization = ctx.headers.authorization
  if (!authorization) {
    const error = new Error(errorTypes.UNAUTHORIZATION)
    ctx.app.emit('error', error, ctx)
  }
  const token = authorization.replace('Bearer ', '')
  try {
    const result = jwt.verify(token, PUBLIC_KEY, {
      algorithms: ['RS256']
    })
    // 验证令牌后将登录的用户信息赋值给ctx的user属性，后面处理业务时需要用到用户数据时直接从ctx.user中获取
    ctx.user = result
    await next()
  } catch (err) {
    const error = new Error(errorTypes.UNAUTHORIZATION)
    ctx.app.emit('error', error, ctx)
  }
}

const verifyPermission = (tableName) => {
  return async (ctx, next) => {
    const userId = ctx.user.id
    // 1.获取参数 { commentId: '1' }
    const [resourceKey] = Object.keys(ctx.params)
    const resourceId = ctx.params[resourceKey]
    try {
      const isPermission = await authService.checkPermission(tableName, resourceId, userId)
      if (!isPermission) throw new Error()
      await next()
    } catch (err) {
      const error = new Error(errorTypes.UNPERMISSION)
      return ctx.app.emit('error', error, ctx)
    }
  }
}

module.exports = {
  verifyLogin,
  verifyAuth,
  verifyPermission
}
